/******************************************************************************
 * SAGE - Scalable Adaptive Graphics Environment
 *
 * Module: pixelDownloader.h
 * Author : Byungil Jeong
 *
 * Copyright (C) 2004 Electronic Visualization Laboratory,
 * University of Illinois at Chicago
 *
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the distribution.
 *  * Neither the name of the University of Illinois at Chicago nor
 *    the names of its contributors may be used to endorse or promote
 *    products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Direct questions, comments etc about SAGE to bijeong@evl.uic.edu or 
 * http://www.evl.uic.edu/cavern/forum/
 *
 *****************************************************************************/
 
#ifndef PIXEL_DOWNLOADER_H_
#define PIXEL_DOWNLOADER_H_

#include "sage.h"
#include "sageSync.h"

class pixelDownloader;
class dispSharedData;
class sageMontage;
class sageBlockBuf;
class sagePixelBlock;
class displayContext;
class sageBlockPartition;
class sagePixelReceiver;
class streamProtocol;

class montagePair {
private:
   //int tileID;
   sageMontage *montage[2];
   int frontMon;
   bool renewMontage;
   bool active;
   //bool updated;
   bool clearFlag;

public:   
   montagePair() : renewMontage(false), frontMon(0), active(false), 
         clearFlag(false) {}
   int init(displayContext *context, sagePixFmt pfmt, int index, float depth);
   inline sageMontage* getFrontMon() { return montage[frontMon]; }
   inline sageMontage* getBackMon() { return montage[1-frontMon]; }
   int setDepth(float depth);
   int setLocalTileIdx(int idx);
   void swapMontage();
   int deleteMontage();
   //int getLocalTileIdx() { return montage[0]->tileIdx; }
   inline bool isActive()  { return active; }
   inline void activate()  { active = true, clearFlag = false; }
   inline void deactivate(){ active = false, clearFlag = false; }
   inline void clear()     { clearFlag = true; }
   inline bool getClearFlag() { return clearFlag; }
   
   //void update()    { updated = true; }
   inline void renew()     { renewMontage = true; }
   inline bool isRenewed() { return renewMontage; }
   
   //bool isUpdated() { return updated; }
   //void resetUpdateFlag() { updated = false; }
   ~montagePair();
};

#define PDL_WAIT_CONFIG 1
#define PDL_WAIT_DATA   2
#define PDL_WAIT_SYNC   3

class pixelDownloader {
protected:
   int instID;
   int streamNum;
   int tileNum;
   int updatedFrame, curFrame, syncFrame;
   int configID, dispConfigID;
   int groupSize, blockSize;
   dispSharedData *shared;
   bool frameCheck;
   bool syncOn;
   bool displayActive;
   int  status;
   
   sagePixelReceiver *recv;
   sageBlockBuf *blockBuf;
   montagePair *montageList;

   sageCounter frameCounter;
   int reportRate;
   sageTimer perfTimer;
   unsigned long bandWidth;
   unsigned packetLoss;
   int frameBlockNum;
   int frameSize;
   
   sageBlockPartition *partition;
   sageRect windowLayout;
   int activeRcvs;
   int updateType;
   bool passiveUpdate;
   
   std::deque<char *> configQueue;
   
   //int sendPerformanceInfo();
   int downloadPixelBlock(sagePixelBlock *block, montagePair &monPair);
   int clearTile(int tileIdx);
   int clearScreen();
   int setupSyncInfo(sagePixelBlock *block);
   
public:
   pixelDownloader();
   int init(char *msg, dispSharedData *sh, streamProtocol *nwObj, bool sync);
   int fetchSageBlocks();
   void processSync(int frame, int cmd = 0);
   int enqueConfig(char *data);
   int setDepth(float depth);
   int addStream(int senderID);
   int swapMontages();
   bool reconfigDisplay(int id);
   int evalPerformance(char **frameStr, char **bandStr);
   inline void setReportRate(int rate) { reportRate = rate; }
   inline void resetTimer() { perfTimer.reset(); }
   inline void resetBandWidth() { bandWidth = 0; }
   inline void resetFrame() { frameCounter.reset(); }
   inline int getInstID() { return instID; }   
   inline int getStatus() { return status; }
   
   ~pixelDownloader();
};

#endif
